#ifndef __WIZ_UTILS_CREATOR_TEMPLATE_HPP__SHANHAOBO_19800429__
#define __WIZ_UTILS_CREATOR_TEMPLATE_HPP__SHANHAOBO_19800429__

#include "../../Base/WizBase.hpp"
#include "../../Core/Container/WizDataTypeMap.hpp"
namespace Wiz
{
    namespace Creator
    {
        template<class Param> class Type;
    } /// end of namespace Creator

    namespace Exception
    {
        class InitCreator : public ::Wiz::Exception::Type
        {
            typedef ::Wiz::Exception::Type  tSuper;
        public:
            InitCreator() : tSuper("Init Creator!")
            {}
        public:
        };
    }
} /// end of namespace Wiz

#endif /*__WIZ_UTILS_CREATOR_TEMPLATE_HPP__SHANHAOBO_19800429__*/

#if defined(WIZ_CREATOR_PARAM_COUNT) && (WIZ_CREATOR_PARAM_COUNT >= 0) && (WIZ_CREATOR_PARAM_COUNT < 255)

namespace Wiz
{
    namespace Creator
    {
        namespace WIZ_MPP_COMBINE(RealCreator, WIZ_CREATOR_PARAM_COUNT)
        {
            template <class BasePtrT, class NewT WIZ_COMMA_IF(WIZ_CREATOR_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_CREATOR_PARAM_COUNT, class T)>
            struct Type
            {
                typedef BasePtrT        tBaseAtomPtr;
                static tBaseAtomPtr CreateInstance(WIZ_ENUM_PARAM_XY(WIZ_CREATOR_PARAM_COUNT, T, A))
                {
                    return new NewT(WIZ_ENUM_PARAM_X(WIZ_CREATOR_PARAM_COUNT, A));
                }
            };
        } /// end of namespace RealCreator
    } /// end of namespace Creator
} /// end of namespace Wiz

/// Maybe is included multi times : in same one file
namespace Wiz
{
    namespace Creator
    {
        template<class BasePtrT WIZ_COMMA_IF(WIZ_CREATOR_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_CREATOR_PARAM_COUNT, class T)>
        class Type<BasePtrT(WIZ_ENUM_PARAM_X(WIZ_CREATOR_PARAM_COUNT, T))>
        {
        public:
            WIZ_DECLARE_CLASS_THIS(Type);
            typedef BasePtrT        tBaseAtomPtr;
            typedef tBaseAtomPtr (*tCreateInstance)(WIZ_ENUM_PARAM_X(WIZ_CREATOR_PARAM_COUNT, T));
        public:
            Type() : m_CreateInstance(WIZ_NULLPTR)
            {
            }
        public:
            ::Wiz::Bool::Type IsValid()
            {
                return ::Wiz::IsValidPtr(m_CreateInstance);
            }
            ::Wiz::Bool::Type NotValid()
            {
                return ::Wiz::NotValidPtr(m_CreateInstance);
            }
        public:
            template<class NewT>
            ::Wiz::Void::Type Register()
            {
                typedef ::Wiz::Creator::WIZ_MPP_COMBINE(RealCreator,WIZ_CREATOR_PARAM_COUNT)::Type<tBaseAtomPtr, NewT WIZ_COMMA_IF(WIZ_CREATOR_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_CREATOR_PARAM_COUNT, T)> tRealCreator;
                m_CreateInstance = tRealCreator::CreateInstance;
            }
            ::Wiz::Void::Type Clear()
            {
                m_CreateInstance = WIZ_NULLPTR;
            }
        public:
            tBaseAtomPtr Create(WIZ_ENUM_PARAM_XY(WIZ_CREATOR_PARAM_COUNT, T, A))
            {
                if (::Wiz::NotValidPtr(m_CreateInstance))
                {
                    ::Wiz::Exception::Throw(::Wiz::Exception::InitCreator());
                }
                return m_CreateInstance(WIZ_ENUM_PARAM_X(WIZ_CREATOR_PARAM_COUNT, A));
            }
        protected:
            tCreateInstance         m_CreateInstance;
        };
    } /// end of namespace Creator
} /// end of namespace Wiz

#endif /*#if defined(WIZ_CREATOR_PARAM_COUNT) && (WIZ_CREATOR_PARAM_COUNT >= 0) && (WIZ_CREATOR_PARAM_COUNT < 255)*/
